import { EItemType, EQualityType, IItemDataType } from './ItemBase';
/*
 * @features: 背包管理类
 * @description: 说明
 * @Date: 2020-09-03 13:06:33
 * @Author: judu233(769471424@qq.com)
 * @LastEditTime: 2021-09-12 19:05:42
 * @LastEditors: judu233
 */

import ItemBase from "./ItemBase";
import { StorageUtil } from "../StorageUtil";
import Base from "../Fighting/Base/Base";

const { ccclass, property } = cc._decorator;

/**背包数据 */
export interface IPackageDataType {
    /**最高存储数量 */
    saveCount: number;
    /**当前存储重量 */
    weight: number;
    /**最高存储重量 */
    saveWeight: number;
    /**当前背包等级 */
    level: number;
    /**背包最高级 */
    levelUp: number;
    /**数据 */
    itemData: string;
}

export class BackPackInstence {
    public static backPack: BackPackManager;
}

/**  
    * @Title : 背包管理
    * @Description : 背包管理类
 **/
@ccclass
export default class BackPackManager extends Base {
    /**物品存储key */
    public serializaKey: string = `game:packages`;

    /**背包数据 */
    public data: IPackageDataType;

    /**显示背包物品的节点 */
    @property({
        type: cc.Node,
        displayName: `背包节点`,
        tooltip: `显示背包内容的节点`
    })
    public node_content: cc.Node = null;

    /**当前存储重量 */
    @property({
        type: cc.Label,
        displayName: `存储重量文本`,
        tooltip: `当前存储重量的文本`
    })
    public com_weightLabel: cc.Label = null;
    public get weight(): number {
        return this.checkGet(() => {
            return this.data.weight;
        });
    }
    public set weight(value: number) {
        this.checkSet(() => {
            this.data.weight = value;
            this.weightView(value);
        })
    }
    public weightView(value: number) {
        if (this.com_weightLabel) this.com_weightLabel.string = `${value}`;
    }

    /**当前存储量 */
    @property({
        type: cc.Label,
        displayName: `存储数量文本`,
        tooltip: `当前存储物品的数量`,
    })
    public com_countLabel: cc.Label = null;
    public countView(value: number) {
        if (this.com_countLabel) this.com_countLabel.string = `${value}`;
    }
    /**物品map */
    public itemMap: Map<string, ItemBase> = new Map();
    public get count(): number {
        return this.itemMap.size;
    }

    @property(cc.Prefab)
    public itemPrefab: cc.Prefab = null;

    onLoad() {
        BackPackInstence.backPack = this;
        //test
        this.initBackPack();
    }

    add_item() {
        let node = cc.instantiate(this.itemPrefab);
        let item = node.getComponent(ItemBase);
        item.initItem({
            id: `${this.count + 1}`,
            quality: EQualityType.Tattered,
            type: EItemType.Article,
            level: 0,
            price: 1,
            weight: 2,
            name: `测试物品`,
            description: `一个简单的测试`,
        });
        this.add(item);
    } 

    use_item() {
        this.find(`${this.count}`)?.use();
    }

    re_item() {
        this.throwAway(this.find(`${this.count}`)?.data.id);
    }

    /**初始化背包--加载物品 */
    public initBackPack(maxCount: number = 10, maxWeight: number = 10, maxLevel: number = 10) {
        let isFirst = StorageUtil.getLocalItem(`isFirst`);
        if (!isFirst) {
            this.data = <IPackageDataType>{
                saveCount: maxCount,
                weight: 0,
                saveWeight: maxWeight,
                level: 0,
                levelUp: maxLevel,
            };
            this.serializationBackPack();
            StorageUtil.setLocalItemImmediately(`isFirst`, true);
        } else {
            //从存储中加载物品
            this.data = StorageUtil.getLocalItem(this.serializaKey, []);
            let itemDataStr: [string] = JSON.parse(this.data.itemData);
            let dataList = [];
            //反序列化物品
            for (let [, str] of itemDataStr.entries()) {
                let itemData: IItemDataType = JSON.parse(str);
                let item = cc.instantiate(this.itemPrefab).getComponent(ItemBase);
                item.initItem(itemData);
                dataList.push([itemData.id, item]);
            }
            this.itemMap = new Map(dataList);
        }
        //刷新
        this.refrushView();
    }

    /**序列化保存背包 */
    public serializationBackPack() {
        let itemDataList = [... this.itemMap];
        let result = [];
        //序列化数据
        for (let [id, item] of itemDataList)
            result.push(JSON.stringify(item.data));

        this.data.itemData = JSON.stringify(result);
        StorageUtil.setLocalItemImmediately(this.serializaKey, this.data);
    }

    /**刷新背包物品 */
    public refrushView() {
        this.countView(this.count);
        this.weightView(this.data.weight);
        //刷新布局
        this.refreshUiContent();
    }

    //更新背包布局
    public refreshUiContent() {
        if (!this.node_content) { cc.log(`[背包管理]:背包内容节点为挂载！`); return; }
        let content = this.node_content;
        //遍历更新
        for (let [id, item] of this.itemMap) {
            let node = content.getChildByUuid(item.node.uuid);
            // 添加节点
            if (!node) content.addChild(item.node);
        }
    }

    /**存储物品进背包 */
    public add(item: ItemBase) {
        if (this.isFull()) return "full";
        //判断是否超重
        if (this.isOverweight(item.data.weight)) return "overweight";
        this.data.weight += item.data.weight;
        //存储
        this.itemMap.set(item.data.id, item);
        //刷新
        this.refrushView();
    }

    /**升级背包 */
    public upgrade(level: number = 1) {
        if (!this.isCanUpgrade(level)) return false;
        this.data.levelUp += level;
        return true;
    }

    /**丢弃 */
    public throwAway(itemId: string) {
        let item = this.itemMap.get(itemId);
        if (this.itemMap.delete(itemId)) {
            //删除节点
            item.node.active = false;
            item.node.destroy();
            this.data.weight -= item.data.weight;
            this.refrushView();
        }
    }

    /**查找 */
    public find(itemId: string) {
        for (let [id, item] of this.itemMap)
            if (id == itemId)
                return item;
    }

    /**是否满了 */
    public isFull() {
        if (this.count >= this.data.saveCount) return true;
        else return false;
    }

    /**是否超重 */
    public isOverweight(w: number) {
        let weight = w + this.data.weight;
        if (weight > this.data.saveWeight) return true;
        else false;
    }

    /**是否可以升级 */
    public isCanUpgrade(l: number) {
        let level = l + this.data.levelUp;
        if (level > this.data.levelUp) return false;
        else return true;
    }
}
